﻿// -------------------------------------------------------------------------------------------------------------------------------
// <copyright file="TestConstructor.cs" company="Exul">
//     Copyright (c) Exul. All rights reserved.
// </copyright>
// <author>
//     Exul
// </author>
// -------------------------------------------------------------------------------------------------------------------------------

namespace ExulLibrary.Mathematics.LinearAlgebra.Tests.RMFlattenDenseMatrixTest
{
    #region Usings

    using ExulLibrary.Exceptions;

    using NUnit.Framework;

    #endregion

    /// <summary>
    ///     Test suite for the constructor of <see cref="RMFlattenDenseMatrix{T}"/>.
    /// </summary>
    [TestFixture]
    [Category("ExulLibrary.Mathematics.LinearAlgebra.RMFlattenDenseMatrix{T}")]
    public sealed class TestConstructor
    {
        /// <summary>
        ///     Tests the constructor when size parameters are positive and data parameter is <see langword="null"/>.
        /// </summary>
        /// <param name="rowsCount">
        ///     The number of rows of the new matrix.
        /// </param>
        /// <param name="columnsCount">
        ///     The number of columns of the new matrix.
        /// </param>
        [Test]
        public void WhenSizeParametersArePositiveAndDataIsNull([Values(1, 2)] int rowsCount, [Values(1, 2)] int columnsCount)
        {
            // Act
            var matrix = new RMFlattenDenseMatrix<object>(rowsCount, columnsCount);

            // Assert
            Assert.That(matrix.RowsCount, Is.EqualTo(rowsCount));
            Assert.That(matrix.ColumnsCount, Is.EqualTo(columnsCount));
            Assert.That(matrix.IsSquare, Is.EqualTo(rowsCount == columnsCount));
            Assert.That(matrix.Values, Is.Not.Null & Has.Length.EqualTo(rowsCount * columnsCount));
        }

        /// <summary>
        ///     Tests the constructor when size parameters are positive and data parameter is not <see langword="null"/>
        ///     and has valid size.
        /// </summary>
        /// <param name="rowsCount">
        ///     The number of rows of the new matrix.
        /// </param>
        /// <param name="columnsCount">
        ///     The number of columns of the new matrix.
        /// </param>
        [Test]
        public void WhenSizeParametersArePositiveAndDataIsNotNull([Values(1, 2)] int rowsCount, [Values(1, 2)] int columnsCount)
        {
            // Arrange
            var data = new object[rowsCount * columnsCount];

            // Act
            var matrix = new RMFlattenDenseMatrix<object>(rowsCount, columnsCount, data);

            // Assert
            Assert.That(matrix.RowsCount, Is.EqualTo(rowsCount));
            Assert.That(matrix.ColumnsCount, Is.EqualTo(columnsCount));
            Assert.That(matrix.IsSquare, Is.EqualTo(rowsCount == columnsCount));
            Assert.That(matrix.Values, Is.SameAs(data));
        }

        #if SAFE

        /// <summary>
        ///     Tests the constructor when rowsCount parameter is negative or equal to zero.
        /// </summary>
        /// <param name="rowsCount">
        ///     The number of rows of the new matrix.
        /// </param>
        /// <param name="columnsCount">
        ///     The number of columns of the new matrix.
        /// </param>
        [Test]
        public void WhenRowsCountIsNegativeOrEqualToZero([Values(0, -1)] int rowsCount, [Values(1)] int columnsCount)
        {
            // Act and Assert
            Assert.That(
                () => new RMFlattenDenseMatrix<object>(rowsCount, columnsCount),
                Throws.TypeOf<NegativeOrZeroSizeException>().With.Property("ParamName").EqualTo("rowsCount"));
        }

        /// <summary>
        ///     Tests the constructor when columnsCount parameter is negative or equal to zero.
        /// </summary>
        /// <param name="rowsCount">
        ///     The number of rows of the new matrix.
        /// </param>
        /// <param name="columnsCount">
        ///     The number of columns of the new matrix.
        /// </param>
        [Test]
        public void WhenColumnsCountIsNegativeOrEqualToZero([Values(1)] int rowsCount, [Values(0, -1)] int columnsCount)
        {
            // Act and Assert
            Assert.That(
                () => new RMFlattenDenseMatrix<object>(rowsCount, columnsCount),
                Throws.TypeOf<NegativeOrZeroSizeException>().With.Property("ParamName").EqualTo("columnsCount"));
        }

        /// <summary>
        ///     Tests the constructor when data parameter is not <see langword="null"/> and has no enough elements.
        /// </summary>
        /// <param name="rowsCount">
        ///     The number of rows of the new matrix.
        /// </param>
        /// <param name="columnsCount">
        ///     The number of columns of the new matrix.
        /// </param>
        [Test]
        public void WhenDataParameterIsNotNullAndHasNoEnoughElements([Values(1)] int rowsCount, [Values(1, 2)] int columnsCount)
        {
            // Arrange
            var data = new object[(rowsCount * columnsCount) - 1];

            // Act and Assert
            Assert.That(
                () => new RMFlattenDenseMatrix<object>(rowsCount, columnsCount, data),
                Throws.TypeOf<NoEnoughElementsException>().With.Property("ParamName").EqualTo("data"));
        }

        #endif
    }
}